#include <iostream>
#include <cstdlib>
#include <Poco/File.h>
#include "master/master.h"
#include <map>

#include <Poco/StringTokenizer.h>
using Poco::StringTokenizer;

using namespace std;

using Poco::File;

Master fMaster = Master();

typedef void (*CLI)(string const&, istream &, ostream&, ostream&);

void join ( string const& input, istream & in, ostream& out, ostream& err ){
	out << "Master :: Going to send join to slave" << endl;
	bool error = false;
	string host;
	out << "Master :: Please enter a hostname: ";
	in >> host;
	UInt16 port;
	out << "Master :: Please enter a port: ";
	in >> port;
	if ( port <= 0 || port > UInt16(-1) ) {
		error = true;
		out << "Master::Error::Please enter a port: ";
	}

	if( host.empty()){
		error = true;
		out << "Master::Error::Please enter a host: ";
	}

	if(!error){
		try {
			fMaster.join( host, port );
			out << "Master :: Joined the slave "<< endl;
		} catch (exception e) {
			cout << "Master :: Destination unreachable, please check your information" << endl;
		}
	}

}

void run ( string const& input, istream & in, ostream& out, ostream& err ){
	out << "Going to send run to slave" << endl;

	string comm;
	out << "command: ";
	in >> comm;

	fMaster.command(comm);
}
void put ( string const& input, istream & in, ostream& out, ostream& err ){
	out << "RunMaster :: Put Method" << endl;

	string filename;
	out << "filename: ";
	in >> filename;

	//check if file exists
	out << "RunMaster :: Master going to execute Put" << endl;
	fMaster.put(filename);
	out << "RunMaster :: Put completed" << endl;
}
void get ( string const& input, istream & in, ostream& out, ostream& err ){
	out << "RunMaster :: Get Method" << endl;

	string filename;
	out << "filename: ";
	in >> filename;

	File file(filename);
	out << "RunMaster :: Master going to execute Get" << endl;
	fMaster.get(filename, file);
	out << "RunMaster :: Get completed" << endl;
}

void leave ( string const& input, istream & in, ostream& out, ostream& err ){
	out << "Going to send leave to slave" << endl;
	fMaster.leave();
}

int main(int argc, char ** argv) {
	map< string, CLI> commands;
	commands["join"] = &join;
	commands["run"] = &run;
	commands["put"] = &put;
	commands["get"] = &get;
	commands["leave"] = &leave;

	string command;
	while( true ){
		cout << "Master :: Please enter a command: " << endl;
		cout << "> ";
		cin >> command;

		if (command == "exit") {
			leave("", cin, cout, cerr);
			break;
		}

		StringTokenizer gilgamesj (command, " ", StringTokenizer::TOK_IGNORE_EMPTY);
		CLI cmd = commands[gilgamesj[0]];

		if(cmd != 0){
			cmd(command, cin, cout, cerr);
		}

	}
}
